package cn.wjssl.domain.strategy.repository;

import cn.wjssl.domain.strategy.model.entity.StrategyAwardEntity;
import cn.wjssl.domain.strategy.model.entity.StrategyEntity;
import cn.wjssl.domain.strategy.model.entity.StrategyRuleEntity;
import cn.wjssl.domain.strategy.model.valobj.RuleTreeVO;
import cn.wjssl.domain.strategy.model.valobj.RuleWeightVO;
import cn.wjssl.domain.strategy.model.valobj.StrategyAwardRuleModelVO;
import cn.wjssl.domain.strategy.model.valobj.StrategyAwardStockKeyVO;

import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 和抽奖策略相关的仓储, 在infrastructure层实现
 */
public interface IStrategyRepository {

    // 通过 策略Id 获取对应的 List<StrategyAwardEntity>
    List<StrategyAwardEntity> queryStrategyAwardList(Long strategyId);

    /**
     * 把根据概率生成的奖品池存放到redis中
     * @param key    redis中存的key
     * @param rateRange     奖品池大小
     * @param shuffleStrategyAwardSearchRateTable   awardId对应的map
     */
    void storeStrategyAwardSearchRateTable(String key, int rateRange, Map<Integer, Integer> shuffleStrategyAwardSearchRateTable);

    // 从redis中获取奖品池的大小
    int getRateRange(String key);

    // 抽奖
    Integer getStrategyAwardAssemble(String key, int rateKey);

    // 根据 决策Id 查询对应的 Strategy
    StrategyEntity queryStrategyEntityByStrategyId(Long strategyId);

    // 根据 决策Id, 权重, 查询对应的 StrategyRule
    StrategyRuleEntity queryStrategyRule(Long strategyId, String ruleModel);

    // 根据 决策Id, 规则类型ruleModel, 奖品Id, 查询String类型的 rule_value
    String queryStrategyRuleValue(Long strategyId, String ruleModel, Integer awardId);

    // 根据 决策Id, awardId, 查询奖品对应的 rule_model
    StrategyAwardRuleModelVO queryStrategyAwardRuleModelVO(Long strategyId, Integer awardId);

    // 规则树的构建, 返回规则树VO, RuleTreeVO
    RuleTreeVO queryRuleTreeVOByTreeId(String treeId);

    // 库存存入redis
    void cacheStrategyAwardCount(String cacheKey, Integer awardCount);

    // 扣减库存
    Boolean subtractionAwardStock(String cacheKey, Date endDateTime);

    // 把库存扣减流转对象放入redis的延时队列, 让redis等一会儿再放到阻塞队列中, 让定时队列消费
    void awardStockConsumeSendQueue(StrategyAwardStockKeyVO strategyAwardStockKeyVO);

    // 获取阻塞队列中的头部元素
    StrategyAwardStockKeyVO takeQueueValue();

    // 通过阻塞队列中获取的头部元素, 获得当前消耗的是哪个奖品的库存, 同步Mysql中的库存
    void updateStrategyAwardStock(Long strategyId, Integer awardId);

    // 根据策略ID+奖品ID的唯一值组合，查询奖品信息
    StrategyAwardEntity queryStrategyAwardEntity(Long strategyId, Integer awardId);

    // 根据活动Id, 查询策略Id
    Long queryStrategyIdByActivityId(Long activityId);

    // 根据treeId, 查询规则是rule_lock的节点对应的rule_value
    Map<String, Integer> queryAwardRuleLockCount(String[] treeIds);

    // 用strategyId查询activityId, 然后用userId, activityId, 查询account表, 获取到用户已经抽奖次数
    Integer queryActivityAccountTotalUseCount(String userId, Long strategyId);

    /**
     * 用策略Id, 查询strategy_rule表, 获得权重配置(rule_value)
     * 再通过权重配置, 查询strategy_award表, 查询奖品相关, 组装成权重奖品配置列表ruleWeightVOS
     * 优先从redis中获取
     * @param strategyId
     * @return
     */
    List<RuleWeightVO> queryAwardRuleWeightByStrategyId(Long strategyId);
}
